#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/wait.h>
#include "cmd.h"

void exec_cmd(struct cmd *cmd)
{
	if (builtin_cmd(cmd)) {
        	exit(0);
	} else {
		int fd;
		if (cmd->input != NULL) {
			fd = open(cmd->input, O_CREAT| O_RDONLY, 0666);
			dup2(fd, 0);
			close(fd);
		}
		if (cmd->output != NULL) {
			fd = open(cmd->output, O_CREAT| O_WRONLY| O_TRUNC, 0666);
			dup2(fd, 1);
			close(fd);
		}
		int error = execvp(cmd->argv[0], cmd->argv);
		if (error < 0) { 
			perror("execvp");
			exit(127);
		}
	}		
}

int builtin_cmd(struct cmd *cmd)
{
    if (strcmp(cmd->argv[0], "cd") == 0) {
		chdir(cmd->argv[1]);
        return 1;
	} else if (strcmp(cmd->argv[0], "pwd") == 0) {
		char dir[100];
		getcwd(dir, sizeof(dir));
		printf("%s\n", dir);
        return 1;
	} else if (strcmp(cmd->argv[0], "exit") == 0) {
		exit(0);
        return 1;
	}
    return 0;
}

void exec_pipe_cmd(int cmdc, struct cmd *cmdv)
{
    if (cmdc == 1) {
        exec_cmd(cmdv);
        exit(0);
    }
    int fds[2];
    pipe(fds);
    pid_t pid = fork();
    
    if (pid == 0) {
        dup2(fds[1], 1);
	close(fds[1]);
	close(fds[0]);
        exec_pipe_cmd(cmdc - 1, cmdv);
    }
    
    dup2(fds[0], 0);
    close(fds[0]);
    close(fds[1]);
    exec_cmd(cmdv + cmdc - 1);	
   
}
